/*
 * @Author: 13177709051 3506463075@qq.com
 * @Date: 2024-10-23 19:06:49
 * @LastEditors: 13177709051 3506463075@qq.com
 * @LastEditTime: 2024-10-23 20:08:52
 * @FilePath: /linux22/fifo/namedPipe.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma

#include <iostream>
#include <cstdio>
#include <cerrno>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const std::string comm_path = "./myfifo";
#define DefaultFd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
#define BaseSize 4096

// const std::string comm_path = "./myfifo";: 定义了一个常量字符串，表示命名管道的路径。
// #define DefaultFd -1: 定义一个默认的文件描述符值，表示未打开状态。
// #define Creater 1: 定义创建者标识，用于区分管道的创建者和用户。
// #define User 2: 定义用户标识，用于标识读取或写入管道的用户。
// #define Read O_RDONLY 和 #define Write O_WRONLY: 分别定义读取和写入的打开模式。
// #define BaseSize 4096: 定义缓冲区的大小，用于读取数据。

// 这个类 NamePiped 封装了命名管道的基本操作，提供了创建、打开、读取和写入的接口
class NamePiped
{
private:
    bool OpenNamePipe(int mode)
    {
        _fd = open(_fifo_path.c_str(), mode);
        if(_fd < 0)
            return false;
        return true;
    }

public:
    NamePiped(const std::string &path, int who)
        : _fifo_path(path), _id(who), _fd(DefaultFd)
    {
        if(_id == Creater)
        {
            int res = mkfifo(_fifo_path.c_str(), 0666);
            if(res != 0)
            {
                perror("mkfifo");
            }
            std::cout << "create create named pipe" << std::endl;
        }
    }
    bool OpenForRead()
    {
        return OpenNamePipe(Read);
    }
    bool OpenForWrite()
    {
        return OpenNamePipe(Write);
    }

    int ReadNamePipe(std::string *out)
    {
        char buffer[BaseSize];
        int n = read(_fd, buffer, sizeof(buffer));
        if(n > 0)
        {
            buffer[n] = 0;
            *out = buffer;
        }
        return n;
    }

    int WriteNamePipe(const std::string &in)
    {
        return write(_fd, in.c_str(), in.size());
    }

    ~NamePiped()
    {
        if(_id == Creater)
        {
            int res = unlink(_fifo_path.c_str());
            if(res != 0)
            {
                perror("unlink");
            }
            std::cout << "creater free named pipe" << std::endl;
        }
        if(_fd != DefaultFd) close(_fd);
    }
private:
    const std::string _fifo_path;
    int _id;
    int _fd;
};

// const std::string _fifo_path;: 保存命名管道的路径。
// int _id;: 标识是创建者还是用户。
// int _fd;: 文件描述符，用于读写操作。


// 初始化成员变量: 使用初始化列表设置路径、身份和默认文件描述符。
// 创建管道: 如果 _id 是 Creater，则调用 mkfifo 创建命名管道。如果创建失败，使用 perror 输出错误信息。


// OpenNamePipe(int mode)
// 功能: 封装打开命名管道的逻辑。
// 调用 open 函数尝试打开管道。
// 如果打开失败，返回 false，成功则返回 true。

// OpenForRead() 功能: 调用 OpenNamePipe 以只读模式打开管道。
// OpenForWrite() 功能: 调用 OpenNamePipe 以只写模式打开管道。
// ReadNamePipe(std::string *out) 功能: 从管道读取数据。
// 定义一个缓冲区，调用 read 从文件描述符读取数据。
// 如果读取成功，将数据存入输出参数，并返回读取的字节数。
// WriteNamePipe(const std::string &in) 功能: 向管道写入字符串数据。


// ~NamePiped() 功能: 释放资源和清理工作。
// 如果 _id 是 Creater，则使用 unlink 删除命名管道。
// 关闭文件描述符（如果已打开）。